#ifndef ENTORNO_H_
#define ENTORNO_H_

#include "signalHandlers/Handlers.h"
#include "Usuario.h"
#include "exceptions/DescargaFallidaException.h"
#include <MemoriaCompartida.h>
#include <Semaforo.h>
#include <string.h>
#include <string>
#include <map>

#define MEM_NAME "/usr/include/errno.h"
#define SEM_NAME "/usr/include/err.h"
#define ID_MEM_USRS	'A'
#define ID_MEM_DESC	'B'
#define ID_SEM_USRS	'A'
#define ID_SEM_DESC	'B'
#define MAX_USERS	30
#define MAX_DESCARGAS 30
#define MAS_CHAR_ARRAY 256

using namespace std;

struct mem_usuario{
	int id;
	char nombre[MAS_CHAR_ARRAY];
};

struct mem_usuarios {
	mem_usuario usuarios[MAX_USERS];
};

typedef map<int,string> UsersMapType;

struct mem_descarga {
	int idUsuarioComparte;
	char pathArchivo[MAS_CHAR_ARRAY];
	int idUsuarioDescarga;
	char idDescarga[MAS_CHAR_ARRAY];
};

struct mem_descargas {
	mem_descarga descargas[MAX_DESCARGAS];
};

typedef mem_descarga SolicitudDescargaType;

class Entorno {
private:
	/*
	 * REGISTRO DE USUARIOS CONECTADOS
	 */
	// Buffer con los usuarios conectados
	MemoriaCompartida<mem_usuarios> bufferUsuarios;
	// Semaforo de acceso al buffer de usuario conectados
	Semaforo semaforo;

	/*
	 * REGISTRO DE DESCARGAS
	 */
	// Buffer con solicitudes de descarga
	MemoriaCompartida<mem_descargas> solicitudesDescarga;
	// Semaforo de acceso al buffer de descargas
	Semaforo semaforoDescarga;

	// Usuario del entorno
	Usuario* usuario;

	static Entorno* instance;

	Entorno();
	virtual ~Entorno();

public:
	/*
	 * Devuelve la instancia al entorno
	 */
	static Entorno* getInstance();

	/*
	 * Destruye la instancia
	 */
	static void destroy();

	/*
	 * Agrega al usuario al buffer de Usuarios Conectados
	 */
	int agregarUsuario(Usuario* us);

	/*
	 * Elimina al usuario del buffer de Usuarios Conectados
	 */
	int eliminarUsuario();

	/*
	 * Devuelve un UsersMapType con informacion
	 * de los usuarios conectados
	 */
	UsersMapType obtenerUsuarios();

	/*
	 * Agega un solicitud de descarga al buffer de solicitudes
	 */
	void solicitarDescarga(SolicitudDescargaType sd);

	/*
	 * Consulta si existe una solicitud para usuarioId,
	 * para transferir un archivo
	 */
	SolicitudDescargaType consultarSolicitudDescargaPara(int usuarioId);

	/*
	 * Consulta si existe una solicitud para usuarioId,
	 * para publicar la lista de archivos compartidos
	 */
	SolicitudDescargaType consultarSolicitudPublicarPara(int usuarioId);
};

#endif /* ENTORNO_H_ */
